#include "Orion20m.h"
#include "cvel.h"
//////////////////////
#define log_getconf(_fmt,...) {char lstr[256];\
		sprintf_s(lstr,256,_fmt,__VA_ARGS__);\
		if(logents<=6) {\
			sprintf_s(conflogstr,1024,"%s %s",conflogstr,lstr);logents++;\
		} else {\
			syslog("/etc/rc.d/rc.modules.custom: %s",conflogstr);\
			dprint("Custom .cfg params: %s",conflogstr);\
			sprintf_s(conflogstr,1024,"%s",lstr);\
			logents=1;\
		}\
}
//////////////////////
#define getconfint(d,s) {\
	if (oapiReadItem_int(CFG,s,ivar)) {\
		cfg->d=ivar;\
		log_getconf("%s=%i",s,ivar);\
	}\
}
//////////////////////
#define getconfdouble(d,s) {\
	if ( (oapiReadItem_float(CFG,s,dvar)) && dvar>0) {\
		cfg->d=dvar;\
		log_getconf("%s=%.8g",s,dvar);\
	}\
}
//////////////////////
#define getconfvecD(d,s) {\
	if ( (oapiReadItem_vec(CFG,s,vecvar)) ) {\
		cfg->d=oapiGetColour((DWORD)vecvar.x,(DWORD)vecvar.y,(DWORD)vecvar.z);\
		log_getconf("%s=%.0f,%.0f,%.0f",s,vecvar);\
	}\
}
/////////////////////
#define mkrcslin(i,x1,y1,z1,x2,y2,z2,m) {\
	th_att_lin[i] = CreateThruster (_V(x1,y1,z1), _V(x2,y2,z2), cfg->RCSThrust*m, ph_RCS, cfg->IspRCS, cfg->IspRCS);\
	AddExhaust (th_att_lin[i], RCS_EX_LEN*m, RCS_EX_WIDTH*m, 0.357*m,tex);\
}

/////	
///////////////////////
DLLCLBK VESSEL *ovcInit (OBJHANDLE hvessel, int flightmodel) {
	ORION *Orion= new ORION( hvessel, flightmodel );
	return Orion;
}

/////	
///////////////////////
DLLCLBK void ovcExit (VESSEL *vessel) {
	if (vessel) delete (ORION*)vessel;
}

/////	init.1
///////////////////////
ORION::ORION (OBJHANDLE hObj, int fmodel) : API (hObj) {
	this->cfg = new ORIONCFG();
	this->hdata = new ORIONHUDDATA();

	dprint("ORION: start. loadmesh: P...");
	hOrionP = oapiLoadMeshGlobal( "Orion/Orion20mP");
	dprint("ORION: loadmesh: M...");
	hOrionM = oapiLoadMeshGlobal( "Orion/Orion20mM");
	dprint("ORION: loadmesh: H...");
	hOrionH = oapiLoadMeshGlobal( "Orion/Orion20mH");
	hOrionSc = oapiLoadMeshGlobal( "Orion/Orion20mSc");
	dprint("ORION: loadmesh: done. RegisterExhaustTexture...");
	tex   = oapiRegisterExhaustTexture ("Exhaust");
	dprint("ORION: RegisterExhaustTexture: done.");

	MyID=ConnectToOrbiterSoundDLL3(hObj);
	havesound=true;
	RequestLoadVesselWave3(MyID,5,"Sound\\Orion\\atomicbomb.wav",DEFAULT);
	RequestLoadVesselWave3(MyID,6,"Sound\\Orion\\camzoom.wav",DEFAULT);
	hudfont = oapiCreateFont (16, true, "Fixed", FONT_BOLD);	// fixme: cfg
	// fixme: defaults in class declaration?
	//// .cfg
	cfg->EmptyMass=EmptyMass;
	cfg->MainThrust=MainThrust;
	cfg->RCSThrust=RCSThrust;
	cfg->GyroThrust=GyroThrust;
	cfg->Ispmain=Ispmain;
	cfg->IspRCS=IspRCS;
	cfg->IspGYRO=IspGYRO;
	cfg->FuelMass=FuelMass;
	cfg->RCSFuelMass=RCSFuelMass;
	cfg->GyroFuelMass=GyroFuelMass;
	cfg->DestructRange=DestructRange;
	cfg->Destructive = 1;
	cfg->FlashSize=FlashSize;
	cfg->VisLimit=VisLimit;
	cfg->hudfontcolor=0xAAAA00;
	cfg->hudselcolor=0xFFFF33;
	cfg->hudshadowcolor=0x111111;
	cfg->hudmesgcolor=0xAAAAAA;
	cfg->hudfillcolor=0x555500;
	cfg->verbose=0;
	//// .scn storable
	cfg->hudmode = HUD_MAIN;
	cfg->nukearmed = 1;
	cfg->nukesafety1 = 0;
	cfg->nukesafety2 = 0;
	cfg->nukesafety3 = 0;
	cfg->nukeyield=1.0;
	cfg->rcs_cog_comp=0;
	
	// runtime
	cfg->nukewarned=0;
	cfg->syslogp=0;
	cfg->booting=1;
	cfg->cam=0;
	cfg->camanimlink=1;
	// todo: .cfg
	cfg->hudshadow=true;
	//
	boomcount = 0;
	lcount=0;
	rot_comp_mode = 0;
	rot_comp_level = 0.0;
	sprintf(hudtitle,"[U]: Hud on.");
	rcs_shift_mode = 0;
	rcstimer=0;
	boomtimer=0;
	rcs_shift_vec=_V(0,0,0);
	shipcg=_V(0,0,0);
	SSCOUNT=0;
	ssmass=0.0;
	vhudCreated=0;

	sCAMERAS def[NUMCAMS] = {
		{_V(0,0,38.0), _V(0,0,1), 60.0,"Main"},
		{_V(0,3,38), _V(0,0,1), 61.0,"Cockpit"},
		{_V(0,7.655,17), _V(0,0,1), 62.0,"Zenith docking tower"},
		{_V(0,9.555,-2.1), _V(0,0,1), 62.0,"Rear (Zenith)"}
	};
	for(int i=0;i<NUMCAMS;i++) { // I hate you, Milkman Dan.
		defcams[i]=def[i];
	}
	
/* meanie
	cameras[] = {
		{_V(0,0,38.0),_V(0,0,1),60.0,0.0,0.0},
		{_V(0,7.655,17),_V(0,0,1),60.0,0.0,0.0},
		{_V(0,3,38),_V(0,0,1),60.0,0.0,0.0}
	};*/
	// fixme: find perlish declare @cameras=({apt=>x,dir=>x,pos=>x},{apt=...
#ifdef CVEL
	dprint("ORION: using cvel...");
	CheckCentralMessage(); 
	ph_main=NULL;
#endif
	syslog("ORION v%f booting%s...",OrionVersion,(DEBUG>0?"... debug: ON":""));
	dprint("ORION: done");
}

/////	init.2
///////////////////////
void ORION::clbkSetClassCaps(  FILEHANDLE CFG ) {
	//syslog("/etc/rc.S: [OK]");
	dprint("clbkSetClassCaps: start");
	int ivar,logents;double dvar;VECTOR3 vecvar;
	logents=0;
	char conflogstr[1024];
	sprintf(conflogstr,"");
	getconfdouble(EmptyMass,"EmptyMass");
	getconfdouble(MainThrust,"MainThrust");
	getconfdouble(RCSThrust,"RCSThrust");
	getconfdouble(GyroThrust,"GyroThrust");
	getconfdouble(Ispmain,"Ispmain");
	getconfdouble(IspRCS,"IspRCS");
	getconfdouble(IspGYRO,"IspGYRO");
	getconfdouble(GyroFuelMass,"GyroFuelMass");
	getconfdouble(RCSFuelMass,"RCSFuelMass");
	getconfdouble(FuelMass,"FuelMass");
	getconfdouble(DestructRange,"DestructRange");
	getconfint(Destructive,"Destructive");
	getconfint(verbose,"Verbose");
	getconfdouble(FlashSize,"FlashSize");
	getconfdouble(VisLimit,"VisLimit");
	getconfvecD(hudfontcolor,"HudFontColor");
	getconfvecD(hudshadowcolor,"HudShadowColor");
	getconfvecD(hudselcolor,"HudSelColor");
	getconfvecD(hudmesgcolor,"HudMesgColor");
	getconfvecD(hudfillcolor,"HudFillColor");
	if(logents>0) {
		syslog("/etc/rc.d/rc.modules.custom: %s",conflogstr);
		dprint("Custom .cfg params: %s",conflogstr);
	}
	SetUpOrion();
	syslog("/etc/rc.d/rc.modules: [OK] - Hardware control online.",GetEmptyMass());
	clbkSetClassCaps_UMMu();
	dprint("clbkSetClassCaps: done");
}
/////	init.2.1
///////////////////////
void ORION::SetUpOrion() {
	dprint("SetUpOrion: start");
	ph_main=NULL;
	slam_proc = 0.0;
	sc_proc = 0.0;
	//testcamx_proc = 0.0;
//	jiggle_proc = -1.0;
//	bombcounter = 0;
	numevas = 0;
	firstnukestep = true;

	sDOCKS defdocks[NUMDOCKS] = {
		{_V( 0.0, 0.0 , 42.0), _V( 0, 0, 1), _V(0,1, 0),NULL,NULL,NULL,FALSE,1.0,"EVA"},
		{_V( 3.6, 0.0 , 33.575), _V( 1, 0, 0), _V(0,0,-1),NULL,NULL,NULL,FALSE,1.0,"EVA"},
		{_V(-3.6, 0.0 , 33.575), _V(-1, 0, 0), _V(0,0,-1),NULL,NULL,NULL,FALSE,1.0,"EVA"},
		{_V( 0.0, 3.8 , 26.6), _V(0,  1, 0), _V(0,0, 1),NULL,NULL,NULL,FALSE,1.0,"EVA"},
		{_V( 0.0,-3.8 , 26.6), _V(0, -1, 0), _V(0,0, 1),NULL,NULL,NULL,FALSE,1.0,"EVA"},
		{_V( 3.6, 0.0 , 23.9), _V( 1, 0, 0), _V(0,0, 1),NULL,NULL,NULL,FALSE,1.0,"EVA"},
		{_V(-3.6, 0.0 , 23.9), _V(-1, 0, 0), _V(0,0, 1),NULL,NULL,NULL,FALSE,1.0,"EVA"},
		{_V( 0.0, 6.5 , 18.2), _V( 0, 0, 1), _V(0,1, 0),NULL,NULL,NULL,FALSE,1.0,"EVA"},
		{_V( 0.0, -6.50 , 18.2), _V(0, 0, 1), _V(0,-1, 0),NULL,NULL,NULL,FALSE,1.0,"EVA"}
	};
	for (int i=0;i<NUMDOCKS;i++) {
		docks[i]=defdocks[i];
		docks[i].handle=CreateDock (docks[i].pos, docks[i].dir, docks[i].rot);
	}

//fwd dock cam 0 1 41.5
//up/rear 0 10.5 -0.6
//down/rear 0 -10.5 -0.6

	CAMforward = CreateAttachment(false,_V(0.0,1.0,41.5),_V(0,0,1),_V(0,1,0),"CAMforward",false);
	CAMuprear = CreateAttachment(false,_V(0.0,10.5,-0.6),_V(0,0,-1),_V(0,1,0),"CAMuprear",false);
	CAMdownrear = CreateAttachment(false,_V(0.0,-10.5,-0.6),_V(0,0,-1),_V(0,-1,0),"CAMdownrear",false);


	SetSize (45);
	SetTouchdownPoints (_V(0,8.0,-24), _V(6,-8.0,-24), _V(-6,-8.0,-24));
	SetPMI (_V(134,117,52));
	SetCrossSections (_V(84,115,35));
	SetCW (0.13, 0.5, 1.4, 1.4);
	SetRotDrag (_V(1.5,1.0,1.0));
	SetPitchMomentScale (1e-6);
	SetBankMomentScale (1e-6);
	ph_main = CreatePropellantResource( cfg->FuelMass );
	SetDefaultPropellantResource( ph_main );

	ph_RCS = CreatePropellantResource(cfg->RCSFuelMass);
	ph_GYRO = CreatePropellantResource(cfg->GyroFuelMass);
#ifdef CVEL
	SetEmptyMass ( cfg->EmptyMass + CalculateMass () );
//	SetEmptyMass ( CalculateMass (EmptyMass));
	MoveNegative=true;
//	AddMesh( hOrion, &pos );
	ClearMeshesEx();
	PlaceComponents();
    Draw(_V(0,0,0));
#endif
	//SetCameraOffset(_V(0,0,41.0));
	SetCameraOffset(CAMERAOFS);
	SetOrionStage();
	EnableTransponder(true);
	UnDockArm = false;
//	syslog("init: done.");
	dprint("SetUpOrion: done.",GetEmptyMass());

	SetVisibilityLimit(cfg->VisLimit);
}
/////	init.2.1.1
///////////////////////
void ORION::PlaceComponents()
{
	dprint("PlaceComponents: start");
	VECTOR3 pos;
#ifdef CVEL
	COMMON_MESH tmp;

	pos = _V(0,0,-13.0);
	tmp.MeshHandle(hOrionP);			// Propulsion module
	tmp.MeshPosition( pos);				// Pusher, struts, and many of the bombs
	AddMeshEx( tmp);

	pos = _V( 0,0,7.5 );
	tmp.MeshHandle(hOrionM);			// Magazine (fuel tanks, sorta)
	tmp.MeshPosition( pos);				// Note:  Magazine also includes some storage
	AddMeshEx( tmp);					//		for mission payload

	pos = _V(0,0,29.0);
	tmp.MeshHandle(hOrionH);			// Hab area
	tmp.MeshPosition( pos);				// Hab, docking areas, and much else
	AddMeshEx( tmp);

	for(int i=1;i<NUMCAMS;i++) {
		tmp.MeshHandle(hOrionSc);
		tmp.MeshPosition(defcams[i].pos);
		AddMeshEx(tmp);
	}

#else
	pos = _V(0,0,-13.0);
	AddMesh(hOrionP,&pos);
	pos = _V( 0,0,7.5 );
	AddMesh(hOrionM,&pos);
	pos = _V(0,0,29.0);
	AddMesh(hOrionH,&pos);
#endif
	dprint("PlaceComponents: done");
}
/////	init.2.1.2
///////////////////////
void ORION::SetOrionStage( ) {
	dprint("SetOrionStage: start");

	PARTICLESTREAMSPEC contrail = 
	{
		0, 5.0, 5, 250, 0.3, 4.0, 16, 3.0, PARTICLESTREAMSPEC::DIFFUSE,
		PARTICLESTREAMSPEC::LVL_SQRT, 0, 1,
		PARTICLESTREAMSPEC::ATM_PLOG, 1e-4, 1
	};

	PARTICLESTREAMSPEC exhaust_main = {
		0, 300, 0.5, 500, 0, 7, 50, 0.0, PARTICLESTREAMSPEC::EMISSIVE,
		PARTICLESTREAMSPEC::LVL_SQRT, 0, 1,
		PARTICLESTREAMSPEC::ATM_PLOG, 0, 0.1
	};
	exhaust_main.tex = oapiRegisterParticleTexture ("Contrail2");

/*	CreateAirfoil (LIFT_VERTICAL,   _V(0,0,-0.5), VLiftCoeff, 20, 270, 2.266);
	CreateAirfoil (LIFT_HORIZONTAL, _V(0,0,-4), HLiftCoeff, 20,  50, 1.5);

	CreateControlSurface (AIRCTRL_ELEVATOR, 5.0, 1.5, _V( 0, 0,  -15), AIRCTRL_AXIS_XPOS);
	CreateControlSurface (AIRCTRL_RUDDER,   2.0, 1.5, _V( 0, 3,  -16), AIRCTRL_AXIS_YPOS);
	CreateControlSurface (AIRCTRL_AILERON,  3.0, 1.5, _V( 7,-0.5,-15), AIRCTRL_AXIS_XPOS);
	CreateControlSurface (AIRCTRL_AILERON,  3.0, 1.5, _V(-7,-0.5,-15), AIRCTRL_AXIS_XNEG);

	PARTICLESTREAMSPEC rps = {
		0, 20, 20, 0, 0.03, 0.5, 100, 3, PARTICLESTREAMSPEC::DIFFUSE,
		PARTICLESTREAMSPEC::LVL_FLAT, 1, 1, PARTICLESTREAMSPEC::ATM_PLIN, 6e7, 12e7
	};
	AddReentryStream (&rps);
*/

	static UINT SlamGrp[5] = {1, 2, 3, 6, 8};		// 1, 2, 3, 5, 6, 8.  #9 is highest
	static MGROUP_TRANSLATE Slam (0, SlamGrp, 5,
		_V(0.0,0.0, 10.5));
	//MGROUP_TRANSLATE (_mesh, _grp, _ngrp, const VECTOR3 &_shift)
	//	: MGROUP_TRANSFORM (_mesh, _grp, _ngrp), shift(_shift) {}

	anim_slam = CreateAnimation (1.0);
	AddAnimationComponent (anim_slam, 0.0, 1.0, &Slam);
	SetAnimation (anim_slam, slam_proc);

	static UINT CamyawGrp[2] = {1, 2};
	static UINT CammountGrp[1] = {2};
	static UINT CamscopeGrp[1] = {1};



	cameras[0]=defcams[0];
	for(int i=1;i<NUMCAMS;i++) {
		ANIMATIONCOMPONENT_HANDLE parent;
		int meshnum=2+i;
		cameras[i]=defcams[i];

		cameras[i].yaw_proc = 0.0;
		cameras[i].anim_yaw= CreateAnimation (1.0);
		parent=AddAnimationComponent (
			cameras[i].anim_yaw, 
			0.0, 
			1.0, 
			new MGROUP_ROTATE (meshnum, CammountGrp, 1, _V(0,0,0), _V(0,1,0), (float) (2 * PI))
		);
		//AddAnimationComponent (cameras[i].anim_yaw, 0.0, 1.0, new MGROUP_ROTATE (meshnum, CamyawGrp, 2, _V(0,0,0), _V(0,1,0), (float) (2 * PI)));
		SetAnimation (cameras[i].anim_yaw, cameras[i].yaw_proc);

		cameras[i].pitch_proc = 0.0;
		cameras[i].anim_pitch= CreateAnimation (1.0);
		AddAnimationComponent (
			cameras[i].anim_pitch, 
			0.0, 
			1.0, 
			new MGROUP_ROTATE (meshnum, CamscopeGrp, 1, _V(0,0.195,0), _V(1,0,0), (float) (2 * PI) ),
			parent
		);
		SetAnimation (cameras[i].anim_pitch, cameras[i].pitch_proc);
	}

	th_main[0] = CreateThruster (ExplosionPosition,    _V( 0.0,0.0,1.0), 
		1.0, ph_main, cfg->Ispmain, cfg->Ispmain);
	th_orion[0] = CreateThruster (ExplosionPosition,    _V( 0.0,0.0,1.0), 
		cfg->MainThrust, ph_main, cfg->Ispmain, cfg->Ispmain);

	thg_main  = CreateThrusterGroup( th_main, 1, THGROUP_MAIN );
	thg_orion = CreateThrusterGroup( th_orion, 1, THGROUP_USER );

//	cloud = AddExhaustStream (th_orion[0],ExplosionPosition, &exhaust_main);
	SoundOptionOnOff3(MyID,PLAYMAINTHRUST,FALSE);
	SoundOptionOnOff3(MyID,PLAYATTITUDETHRUST,FALSE);

	nuke = AddExhaust (th_orion[0], 1.0, 100.0, tex);
	SetThrusterGroupLevel(thg_orion, 0.0);
	COLOUR4 col_d = {0.9,0.9,0.8,0};
	COLOUR4 col_s = {0.9,0.9,0.8,0};
	COLOUR4 col_a = {0,0,0,0};
	COLOUR4 col_white = {1,1,1,0};
	boom= AddPointLight (_V(0,0,-200), 5000, 1e-4, 0, 2e-4, col_d, col_s, col_a);
	boom->SetIntensity(2);
	boom->Activate(0);
	dprint("SetOrionStage: SetAttControlsOrion");
	SetAttControlsOrion();
	EnableTransponder(true);
	dprint("SetOrionStage: done");
}
/////	init.2.1.2.1
///////////////////////
void ORION::SetAttControlsOrion() {
	dprint("SetAttControlsOrion");
	//	VECTOR3 v_com; double plmass; plmass = CalculateMass(&v_com); double comshift = -1.0*(v_com.z * plmass)/(GetMass());
	double comshift = 0.0;
	#define RCS_EX_WIDTH 0.15
	#define RCS_EX_LEN 1.5

	THRUSTER_HANDLE th_att_rot[4], th_att_lin[4];

	//CreateThruster (&pos, &dir, maxth0, hp, isp0, isp_ref, p_ref)

	th_att_rot[0] = CreateThruster (_V(0,-1.8, 24.0-comshift), _V(0, 1,0), cfg->GyroThrust, ph_GYRO, cfg->IspGYRO, cfg->IspGYRO);
	th_att_rot[1] = CreateThruster (_V(0, 4.9,-24.0-comshift), _V(0,-1,0), cfg->GyroThrust, ph_GYRO, cfg->IspGYRO, cfg->IspGYRO);
	th_att_rot[2] = CreateThruster (_V(0, 1.8, 24.0-comshift), _V(0,-1,0), cfg->GyroThrust, ph_GYRO, cfg->IspGYRO, cfg->IspGYRO);
	th_att_rot[3] = CreateThruster (_V(0,-4.9,-24.0-comshift), _V(0, 1,0), cfg->GyroThrust, ph_GYRO, cfg->IspGYRO, cfg->IspGYRO);
	CreateThrusterGroup (th_att_rot,   2, THGROUP_ATT_PITCHUP);
	CreateThrusterGroup (th_att_rot+2, 2, THGROUP_ATT_PITCHDOWN);

	th_att_rot[0] = CreateThruster (_V( 1.8,0, 24.0-comshift), _V(-1,0,0), cfg->GyroThrust, ph_GYRO, cfg->IspGYRO, cfg->IspGYRO);
	th_att_rot[1] = CreateThruster (_V(-4.9,0,-24.0-comshift), _V( 1,0,0), cfg->GyroThrust, ph_GYRO, cfg->IspGYRO, cfg->IspGYRO);
	th_att_rot[2] = CreateThruster (_V(-1.8,0, 24.0-comshift), _V( 1,0,0), cfg->GyroThrust, ph_GYRO, cfg->IspGYRO, cfg->IspGYRO);
	th_att_rot[3] = CreateThruster (_V( 4.9,0,-24.0-comshift), _V(-1,0,0), cfg->GyroThrust, ph_GYRO, cfg->IspGYRO, cfg->IspGYRO);
	CreateThrusterGroup (th_att_rot,   2, THGROUP_ATT_YAWLEFT);
	CreateThrusterGroup (th_att_rot+2, 2, THGROUP_ATT_YAWRIGHT);

	th_att_rot[0] = CreateThruster (_V( 4.8,0,0), _V(0, 1,0), cfg->GyroThrust, ph_GYRO, cfg->IspGYRO, cfg->IspGYRO);
	th_att_rot[1] = CreateThruster (_V(-4.8,0,0), _V(0,-1,0), cfg->GyroThrust, ph_GYRO, cfg->IspGYRO, cfg->IspGYRO);
	th_att_rot[2] = CreateThruster (_V(-4.8,0,0), _V(0, 1,0), cfg->GyroThrust, ph_GYRO, cfg->IspGYRO, cfg->IspGYRO);
	th_att_rot[3] = CreateThruster (_V( 4.8,0,0), _V(0,-1,0), cfg->GyroThrust, ph_GYRO, cfg->IspGYRO, cfg->IspGYRO);
	CreateThrusterGroup (th_att_rot,   2, THGROUP_ATT_BANKLEFT);
	CreateThrusterGroup (th_att_rot+2, 2, THGROUP_ATT_BANKRIGHT);


	mkrcslin(0, 3.8,-3.8,30.0, 0,1,0, 1);
	mkrcslin(1, -3.8,-3.8,30.0, 0,1,0, 1);
	mkrcslin(2, 7,-7,-7.5, 0,1,0, 4);
	mkrcslin(3, -7,-7,-7.5, 0,1,0, 4);
	CreateThrusterGroup (th_att_lin,   4, THGROUP_ATT_UP);

	mkrcslin(0, 3.8,3.8,30.0, 0,-1,0, 1);
	mkrcslin(1, -3.8,3.8,30.0, 0,-1,0, 1);
	mkrcslin(2, 7,7,-7.5, 0,-1,0, 4);
	mkrcslin(3, -7,7,-7.5, 0,-1,0, 4);
	CreateThrusterGroup (th_att_lin,   4, THGROUP_ATT_DOWN);

	mkrcslin(0, 3.8,3.8, 30.0, -1,0,0, 1);
	mkrcslin(1, 3.8,-3.8, 30.0, -1,0,0, 1);
	mkrcslin(2, 7,7,-7.5, -1,0,0, 4);
	mkrcslin(3, 7,-7,-7.5, -1,0,0, 4);
	CreateThrusterGroup (th_att_lin,   4, THGROUP_ATT_LEFT);

	mkrcslin(0, -3.8,3.8, 30.0, 1,0,0, 1);
	mkrcslin(1, -3.8,-3.8, 30.0, 1,0,0, 1);
	mkrcslin(2, -7,7,-7.5, 1,0,0, 4);
	mkrcslin(3, -7,-7,-7.5, 1,0,0, 4);
	CreateThrusterGroup (th_att_lin,   4, THGROUP_ATT_RIGHT);

	mkrcslin(0, 7,-7,-7.5, 0,0,1, 2);
	mkrcslin(1, 7,7,-7.5, 0,0,1, 2);
	mkrcslin(2, -7,-7,-7.5, 0,0,1, 2);
	mkrcslin(3, -7,7,-7.5, 0,0,1, 2);
	CreateThrusterGroup (th_att_lin,   4, THGROUP_ATT_FORWARD);

	mkrcslin(0, 3.8,-3.8,30.0, 0,0,-1, 1);
	mkrcslin(1, 3.8,3.8,30.0, 0,0,-1, 1);
	mkrcslin(2, -3.8,-3.8,30.0, 0,0,-1, 1);
	mkrcslin(3, -3.8,3.8,30.0, 0,0,-1, 1);
	CreateThrusterGroup (th_att_lin, 4, THGROUP_ATT_BACK);
}

/////	init.3
///////////////////////
void ORION::clbkLoadStateEx(FILEHANDLE scn, void *vs)
{
	cfg->booting=1;
	dprint("clbkLoadStateEx: start");
    char *line;
	int ivar,ivar2,ivar3;
	float fvar,fvar2,fvar3,fvar4;
	double dvar,dvar2,dvar3;
	while (oapiReadScenario_nextline (scn, line)) 
	{
		/* CVE-lite function ! */
		/* IMPORTANT */
		/* Call this for every line in the scenario file. It will automatically
		/* deduce which lines are for it, and load the payloads from the file. */

		/* load payload lines */
#ifdef CVEL
		ParsePayloadString(line);
#endif

		ParseScenarioLineEx (line, vs);
		if (!_strnicmp (line, "HUDMODE", 7)) {
			if(sscanf (line +7, "%d", &ivar)) {
				dprint("got HUDMODE: %d",ivar);
				chhud(ivar);
			}
			continue;
		} else if (!_strnicmp (line, "EVASEL", 6)) {
			if(sscanf (line +6, "%d", &ivar)) {
				dprint("got EVASEL: %d",ivar);
				ummu_selectmember(ivar);
			}
			continue;
		} else if (!_strnicmp (line, "DOCKSEL", 7)) {
			if(sscanf (line +7, "%d", &ivar)) {
				dprint("got DOCKSEL: %d",ivar);
				ummu_selectdock(ivar);
			}
			continue;
		} else if (!_strnicmp (line, "DOCKLIGHT", 9)) {
			if(sscanf (line +9, "%d", &ivar)) {
				dprint("got DOCKLIGHT: %d",ivar);
				if(ivar==1) docklight();
			}
			continue;
		} else if (!_strnicmp (line, "COG_COMP", 8)) {
			if(sscanf (line +8, "%d", &ivar)) {
				dprint("got COG_COMP: %d",ivar);
				cfg->rcs_cog_comp=ivar;
			}
			continue;
		} else if (!_strnicmp (line, "NUKEYIELD", 9)) {
			if(sscanf (line +9, "%f", &fvar)) {
				dprint("got NUKEYIELD: %f",fvar);
				if(fvar >= 0.10 && fvar <= 1.0) cfg->nukeyield=fvar;
			}
			continue;
		} else if (!_strnicmp (line, "NUKEARMED", 9)) {
			if(sscanf (line +9, "%d", &ivar)) {
				dprint("got NUKEARMED: %d",ivar);
				cfg->nukearmed=ivar;
			}
			continue;
		} else if (!_strnicmp (line, "NUKESAFE", 8)) {
			if(sscanf (line +8, "%d %d %d", &ivar,&ivar2,&ivar3)) {
				dprint("got NUKESAFE: %d %d %d",ivar,ivar2,ivar3);
				cfg->nukesafety1=ivar;
				cfg->nukesafety2=ivar2;
				cfg->nukesafety3=ivar3;
			}
			continue;
		} else if (!_strnicmp (line, "CAMERA", 6)) {
			if(sscanf (line +6, "%d", &ivar)) {
				dprint("got CAMERA: %d",ivar);
				cfg->cam=min(NUMCAMS-1,max(0,ivar));
				chcam(cfg->cam);
			}
			continue;
		} else if (!_strnicmp (line, "CAMSET", 6)) {
			if(sscanf (line+6, "%d %lf %lf %lf", &ivar,&dvar,&dvar2,&dvar3)==4) {
//				syslog("Got CAMSET: %d / %f %f / %f",ivar,dvar,dvar2,dvar3);
				if(ivar > 0 && ivar < NUMCAMS) {

					cameras[ivar].yaw_proc=min(1.0,max(0.0,dvar));
					SetAnimation(cameras[ivar].anim_yaw, cameras[ivar].yaw_proc);

					cameras[ivar].pitch_proc=min(1.0,max(0.0,dvar2));
					SetAnimation(cameras[ivar].anim_pitch, cameras[ivar].pitch_proc);

					cameras[ivar].apt=min(60.0,max(0.2,dvar3));
				}
			}
			continue;
		}
		if(Crew.LoadAllMembersFromOrbiterScenario(line)==TRUE) continue;
	}
#ifdef CVEL
	SetEmptyMass ( cfg->EmptyMass + CalculateMass () );
#endif
	/*
	int ivar;
	if(oapiReadItem_int(scn, "HUDMODE", ivar)) {
		dprint("got HUDMODE: %d",ivar);
	}
	*/
	cfg->booting=0;
	syslog("/etc/rc.d/rc.local: [OK] - init: done.");
	dprint("clbkLoadStateEx: done");
}
/////	
///////////////////////

